﻿using System;
using System.Windows.Input;
using YourWorld.Common;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Composite.Regions;
using MainGameModule.Models;
using Microsoft.Practices.Composite.Presentation.Commands;
using MainGameModule.Views;
using BusinessObjects;
using YourWorld.Common.GreenWorldEntitiesService;
using System.Diagnostics;
using YourWorld.Common.Infrastucture.Events;
using System.Linq;

namespace MainGameModule.ViewModels
{
    public class ConnectViewModel : ViewModelBase
    {
        private IUnityContainer container;
        private IRegionManager regionManager;
        private IGameModel gameModel;

        private Player player;
        private string otherPlayerName;

        private bool isConnectTheSamePlayer;
        private bool isConnectAnotherPlayer;
        private bool isConnectPlayerRequest;
        private bool isConnectPlayerResponseReceived;
        private bool isAlreadyConnected;
        private bool showPlayerInfo;

        private string comments;
        private string messageComments;

        private const string DefaultRequestComments = "Hi, do you want to connect with me?";
        private const string DefaultResponseComments = "Hi, I've accepted your connection request! Let's go and take all the Quests!";

        public ConnectViewModel( IUnityContainer container, IRegionManager regionManager, IGameModel gameModel )
        {
            this.container = container;
            this.regionManager = regionManager;
            this.gameModel = gameModel;

            this.CloseCommand = new DelegateCommand<string>( this.CloseView );
            this.SendRequestCommand = new DelegateCommand<string>( this.SendRequest );
            this.ConfirmRequestCommand = new DelegateCommand<string>( this.ConfirmRequest );
            this.ViewQuestsCommand = new DelegateCommand<string>( this.ViewQuests );
        }

        public Player Player
        {
            get
            {
                return this.player;
            }
            set
            {
                if ( this.player == value )
                    return;

                this.player = value;
                this.NotifyPropertyChanged( "Player" );
            }
        }

        public string OtherPlayerName
        {
            get
            {
                return this.otherPlayerName;
            }
            set
            {
                if ( this.otherPlayerName == value )
                    return;

                this.otherPlayerName = value;
                this.NotifyPropertyChanged( "OtherPlayerName" );
            }
        }

        public int OtherPlayerId
        {
            get;
            set;
        }

        public string Comments
        {
            get
            {
                return this.comments;
            }
            set
            {
                if ( this.comments == value )
                    return;

                this.comments = value;
                this.NotifyPropertyChanged( "Comments" );
            }
        }

        public ICommand CloseCommand
        {
            get;
            private set;
        }

        public ICommand SendRequestCommand
        {
            get;
            private set;
        }

        public ICommand ViewQuestsCommand
        {
            get;
            private set;
        }

        public ICommand ConfirmRequestCommand
        {
            get;
            private set;
        }

        public bool IsConnectTheSamePlayer
        {
            get
            {
                return this.isConnectTheSamePlayer;
            }
            set
            {
                if ( this.isConnectTheSamePlayer == value )
                    return;

                this.isConnectTheSamePlayer = value;
                this.NotifyPropertyChanged( "IsConnectTheSamePlayer" );
            }
        }

        public bool IsConnectAnotherPlayer
        {
            get
            {
                return this.isConnectAnotherPlayer;
            }
            set
            {
                if ( this.isConnectAnotherPlayer == value )
                    return;

                this.isConnectAnotherPlayer = value;
                this.NotifyPropertyChanged( "IsConnectAnotherPlayer" );

                this.Comments = DefaultRequestComments;
            }
        }

        public bool IsConnectPlayerRequest
        {
            get
            {
                return this.isConnectPlayerRequest;
            }
            set
            {
                if ( this.isConnectPlayerRequest == value )
                    return;

                this.isConnectPlayerRequest = value;
                this.NotifyPropertyChanged( "IsConnectPlayerRequest" );

                this.Comments = DefaultResponseComments;
            }
        }

        public bool IsConnectPlayerResponseReceived
        {
            get
            {
                return this.isConnectPlayerResponseReceived;
            }
            set
            {
                if ( this.isConnectPlayerResponseReceived == value )
                    return;

                this.isConnectPlayerResponseReceived = value;
                this.NotifyPropertyChanged( "IsConnectPlayerResponseReceived" );
            }
        }

        public bool IsAlreadyConnected
        {
            get
            {
                return this.isAlreadyConnected;
            }
            set
            {
                if ( this.isAlreadyConnected == value )
                    return;

                this.isAlreadyConnected = value;
                this.NotifyPropertyChanged( "IsAlreadyConnected" );
            }
        }

        public string MessageComment
        {
            get
            {
                return this.messageComments;
            }
            set
            {
                if ( this.messageComments == value )
                    return;

                this.messageComments = value;
                this.NotifyPropertyChanged( "MessageComment" );
            }
        }

        public bool ShowPlayerInfo
        {
            get
            {
                return this.showPlayerInfo;
            }
            set
            {
                if ( this.showPlayerInfo == value )
                    return;

                this.showPlayerInfo = value;
                this.NotifyPropertyChanged( "ShowPlayerInfo" );
            }
        }

        public void Initialize()
        {
            this.IsAlreadyConnected = false;
            this.IsConnectTheSamePlayer = false;
            this.IsConnectAnotherPlayer = false;
            this.IsConnectPlayerRequest = false;
            this.IsConnectPlayerResponseReceived = false;
            this.ShowPlayerInfo = false;
        }

        private void SendRequest( string notUsed )
        {
            this.CloseView( String.Empty );

            PlayerConnectionMessage payload = new PlayerConnectionMessage()
            {
                SenderId = this.OtherPlayerId,
                TargetId = this.Player.Id,
                Comments = this.Comments
            };

            this.gameModel.SendPlayerConnectionRequest( payload );
        }

        private void ConfirmRequest( string notUsed )
        {
            this.CloseView( String.Empty );                       
            PlayersRepository.Instance.SavePlayerConnectionId( this.OtherPlayerId, this.Player.Id, this.SaveComplete );
        }

        private void SaveComplete( IAsyncResult result )
        {
            PlayerConnectionMessage payload = new PlayerConnectionMessage()
            {
                SenderId = this.Player.Id,
                TargetId = this.OtherPlayerId,
                Comments = this.Comments
            };

            GameMainViewModel vm = this.container.Resolve<GameMainViewModel>();

            Player p = PlayersRepository.Instance.GetPlayer( vm.Player.Id );
            p.Connections.Add( this.Player.Id );
            p.PlayerConnections.Add( this.Player );

            Player q = PlayersRepository.Instance.GetPlayer( this.Player.Id );
            q.Connections.Add( vm.Player.Id );
            q.PlayerConnections.Add( vm.Player );

            // Can I Win a Connection Badge :)
            foreach ( Badge badge in BadgesRepository.Instance.Badges )
            {
                BadgeType type = BadgesRepository.Instance.BadgeTypes.Where( y => y.ID == badge.Type ).FirstOrDefault();
                Debug.Assert( type != null );

                if ( type.Key != null )
                    continue;

                if ( vm.Player.Connections.Count == badge.MinimumItems )
                {
                    this.player.BadgesCollection.Add( BadgesRepository.Instance.GetBadge( badge.ID ) );
                    EventService.Aggregator.GetEvent<ShowBadgesEvent>().Publish( badge.ID );
                    break;
                }
            }

            this.gameModel.SendPlayerConnectionResponse( payload );
        }

        private void ViewQuests( string notUsed )
        {
            this.CloseView( String.Empty );

            if ( this.regionManager.Regions[RegionNames.GamePopUpRegion].Views.Contains( this.container.Resolve<GameEventsView>() ) == false )
                this.regionManager.RegisterViewWithRegion( RegionNames.GamePopUpRegion, typeof( GameEventsView ) );

            this.regionManager.Regions[RegionNames.GamePopUpRegion].Activate( this.container.Resolve<GameEventsView>() );

        }

        private void CloseView( string notUsed )
        {
            this.regionManager.Regions[RegionNames.GamePopUpRegion].Deactivate( this.container.Resolve<ConnectView>() );

            GameMainView mainView = this.container.Resolve<GameMainView>();
            mainView.CancelDrag();

            PlayerStatusManager.Instance.ContinueGame();
        }
    }
}
